﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Threading;
using Tetris.Controler;
using Tetris.Model;

namespace Tetris.View
{
    /// <summary>
    /// Interaction logic for TetrisView.xaml
    /// </summary>
    public partial class TetrisView : Window
    {
        private ITetrisControler _tetrisControler;
        private ITetrisModel _tetrisModel;
        public object Locker = new object();

        private Color[] _Colors = {Colors.Red, Colors.Blue, Colors.Green, Colors.Yellow, Colors.Violet};
        private Color _NextColor = Colors.Blue;
        
        public TetrisView(ITetrisControler controler, ITetrisModel tetrisModel)
        {
            InitializeComponent();
            this._tetrisControler = controler;
            this._tetrisModel = tetrisModel;

            this.BindModelToViewCanvas();
        }

        public void StartGame()
        {
            while(!this._tetrisModel.EndOfGame)
            {
                if (this._semafor)
                {
                    this._tetrisControler.UserCommand("Down");
                    Thread.Sleep( (500 - this._tetrisModel.Score*2) >0 ? (500 - this._tetrisModel.Score*2) : 1) ;
                }
            }

            this.canvas1.Dispatcher.Invoke(DispatcherPriority.Normal, new Action(
                                                               () =>
                                                                   {
                                                                       var lbl = new Label();
                                                                       lbl.FontSize = 35;
                                                                       lbl.FontFamily = new FontFamily("Arial");
                                                                       lbl.Foreground = new SolidColorBrush(Colors.Black);
                                                                       lbl.Content = "Game Over";
                                                                       this.canvas1.Children.Add(lbl);
                                                                   }           
                                                                   ));
        }

        public void BindCurrentModelToView(IElementModel elementModel)
        {
            this.BindModelToView(elementModel, canvas1, true);
        }

        public void BindNextModelToView(IElementModel elementModel)
        {
            var randomer = new Random();
            var colorIndex = randomer.Next(4);
            this._NextColor = this._Colors[colorIndex];

            this.canvas3.Dispatcher.Invoke(new Action(() =>
            {
                if (this.canvas3.Children.Count > 0)
                {
                    this.canvas3.Children.Clear();
                }
            }

                                               ));

            this.BindModelToView(elementModel, canvas3, false);
        }

        private void BindModelToView(IElementModel elementModel, Canvas canvas, bool bindPosition) //raczej nie powinno sie w modelu okreslac pozycji klocka
        {

            lock (this.Locker)
            {
                foreach (var blockModel in elementModel.BlocksCollection)
                {
                    var blockView = new Rectangle();

                    blockView.DataContext = blockModel;

                    blockView.SetBinding(WidthProperty, "Width");
                    blockView.SetBinding(HeightProperty, "Height");

                    blockView.SetBinding(Canvas.TopProperty, "Top");
                    if (bindPosition)
                    {
                        blockView.SetBinding(Canvas.LeftProperty, "Left");
                    }
                    else
                    {
                        blockView.SetValue(Canvas.LeftProperty, (double)(blockModel.Left - 60));  // bardzo brzydka linijka, chodzi przesuwanie na sztywno o 60
                    }

                    blockView.Fill = new SolidColorBrush( this._NextColor );
                    blockView.Stroke = new SolidColorBrush(Colors.White);
                    blockView.StrokeThickness = 1;

                    canvas.Dispatcher.Invoke(DispatcherPriority.Normal,
                                                    new Action(() => canvas.Children.Add(blockView))
                                                    );
                }
            }
        }

        public void OnBlockDeleted(int index)
        {
            lock (this.Locker)
            {
                this.canvas1.Children.RemoveAt(index);
            }
        }

        public void OnLineDeleted(int line)
        {

            lock (this.Locker)
            {
                this.canvas1.Dispatcher.Invoke(DispatcherPriority.Normal,
                                               new Action(() =>
                                                              {
                                                                  var indexesToDelete = new List<Rectangle>();

                                                                  foreach (var child in this.canvas1.Children)
                                                                  {
                                                                      var rectangle = child as Rectangle;
                                                                      if (rectangle != null)
                                                                      {
                                                                          if (Canvas.GetTop(rectangle) == line)
                                                                          {
                                                                              indexesToDelete.Add(rectangle);
                                                                          }
                                                                      }
                                                                  }

                                                                  foreach (var rectangle in indexesToDelete)
                                                                  {
                                                                      this.canvas1.Children.Remove(rectangle);
                                                                  }
                                                              }));
            }
        }

        private bool _semafor = true; 

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (!this._tetrisModel.EndOfGame)
            {
                this._semafor = false;
                this._tetrisControler.UserCommand(e.Key.ToString());
                this._semafor = true;
            }
        }

        private void BindModelToViewCanvas()
        {
            this.canvas1.DataContext = this._tetrisModel;
            this.canvas2.DataContext = this._tetrisModel;
            this.canvas1.SetBinding(WidthProperty, "CanvasWidth");
            this.canvas1.SetBinding(HeightProperty, "CanvasHeight");
            this.canvas1.SetBinding(BackgroundProperty, "CanvasColor");
            this.labelScoreCurrent.SetBinding(ContentProperty, "Score");
        }
    }
}
